function w = l2relax_ps(X, TUN, opt)
% L2-relaxation estimation for portfolio selection. 
% (nest CV by the Sharpe ratio)
%
% TUN = tunning parameter (can be a scalar or vector)
% opt = 1. no shrinkage
%       2. linear shrinkage
%       3. nonlinear shrinkage

    % 1. nest CV or one-time estimation
    if length(TUN) > 1  
        SR = zeros(length(TUN),1);
        for i = 1:length(TUN)            
            SR(i,1) = nest_cv_ps(X,TUN(i),opt); % nest CV with Sharpe ratio
        end        
        % 2. find the best
        [~,IN] = max(SR);       % choose the largest sharpe ratio
        tun = TUN(IN);
    else
        tun = TUN;
    end
    
    % 2. estimate with optimal tuning
    w = l2relax0([],X,tun,opt);        
end

%% nested functions
function RISK = nest_cv_ps(X,tun,opt)
    % 1. construct 5 nested index
    n = size(X,1);
    d = round(n/5);
    tmp = 1:d:n;
    IN = [tmp(1:5)' [tmp(2:5)'-1; n]];
    INt = [ones(4,1) IN(1:4,2)];
    INe = IN(2:end,:);
    if d <= 12         % to avoid the "analytical_shrinkage.m" error
        INt = INt(2:end,:);
        INe = INe(2:end,:);
    end
    % 2. obtain risk for each tuning value
    RISKt = zeros(size(INt,1),1);
    for j = 1:size(INt,1)
        Xt = X(INt(j,1):INt(j,2),:);        
        Xe = X(INe(j,1):INe(j,2),:);
        wt = l2relax0([],Xt,tun,opt);     
        % 2.1 estimate (rough) Sharpe Ratio 
        r = Xe*wt;
        RISKt(j) = mean(r)/std(r); 
    end
    RISK = mean(RISKt);    
end
 

